﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Text.RegularExpressions;

namespace OWANotifier
{
    public class HtmlTableParser
    {

        public class HtmlElement
        {
            public string TagName { get; set; }
            public Dictionary<string, string> Attributes = new Dictionary<string, string>();
            public string InnerHtml { get; set; }
        }

        public HtmlTableParser()
        {

        }

        public static DataSet TableToDataSet(string html, bool plainTextContents)
        {

            bool withHeaders = OpeningTagRE("th").Match(html).Success;
            bool headersParsed = false;

            DataSet ds = new DataSet();

            foreach (HtmlElement tableTag in parseTagCollection(html, "table"))
            {
                DataTable dt = ds.Tables.Add();

                foreach (HtmlElement trTag in parseTagCollection(tableTag.InnerHtml, "tr"))
                {
                    if (withHeaders && (!headersParsed))
                    {
                        foreach (HtmlElement thTag in parseTagCollection(tableTag.InnerHtml, "th"))
                        {
                            DataColumn dc = dt.Columns.Add();
                            try
                            {
                                dc.ColumnName = new string(
                                        ParsePlainText(thTag.InnerHtml).ToCharArray()
                                        .Where(ch => char.IsLetterOrDigit(ch)).ToArray()
                                        );
                            }
                            catch
                            {
                            }
                            dc.DataType = typeof(string);
                        }
                        headersParsed = true;
                    }
                    else
                    {
                        DataRow dr = dt.NewRow();
                        int coli = 0;
                        foreach (HtmlElement tdTag in parseTagCollection(trTag.InnerHtml, "td"))
                        {
                            if (coli < dt.Columns.Count)
                                if (plainTextContents)
                                    dr[coli] = ParsePlainText(tdTag.InnerHtml).Trim();
                                else
                                    dr[coli] = tdTag.InnerHtml;
                            coli++;
                        }
                        dt.Rows.Add(dr);
                    }
                }
            }

            return ds;
        }

        public static Dictionary<string, string> parseFirstTagAttributes(string text, string tag)
        {
            throw new NotImplementedException();
        }



        public static string ParsePlainText(string text)
        {
            string t = text;
            t = OpeningTagRE("").Replace(t, " ");
            t = ClosingTagRE("").Replace(t, " ");
            t = t.Replace("&nbsp;", " ").Replace("&NBSP;", " ");

            t = t.Trim().Replace("\r", " ").Replace("\n", " ");
            t.Trim();
            t = t.Replace("  ", " ");
            return t;
        }


        public static IEnumerable<HtmlElement> parseTagCollection(string text, string tag)
        {
            Regex openRE = OpeningTagRE(tag);
            Regex closeRE = ClosingTagRE(tag);

            int index = 0;
            while (index < text.Length)
            {
                Match start = openRE.Match(text, index);
                if (!start.Success)
                {
                    break;
                }
                else
                {
                    Match end = closeRE.Match(text, start.Index + start.Length);
                    if (!end.Success)
                    {
                        break;
                    }
                    else
                    {
                        yield return new HtmlElement
                        {
                            TagName = tag,
                            InnerHtml = text.Substring(
                                   start.Index + start.Length,
                                   end.Index - (start.Index + start.Length)
                                   )
                        };
                        index = end.Index + end.Length;
                    }
                }
            }
        }

        public static Regex OpeningTagRE(string tagName)
        {
            return new Regex(string.Format("<{0}[^>]*>", tagName), RegexOptions.IgnoreCase);
        }
        public static Regex ClosingTagRE(string tagName)
        {
            return new Regex(string.Format("</{0}[^>]*>", tagName), RegexOptions.IgnoreCase);
        }



    }




}
